(function () {

    let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"

    const btnControl = document.getElementById("btn_control");
    const sendControl = document.getElementById("btn_send");
    const chatBoxControl = document.getElementById("chat_box");
    let box = document.getElementById("box");

    const recorder = new RecorderManager("./js/xfyun/");
    recorder.onStart = () => {
        changeBtnStatus("OPEN");
    }
    let iatWS;
    let resultText = "";
    let resultTextTemp = "";
    let countdownInterval;
    let chatWS;
    let text = [{"role": "user", "content": "请扮演面试者回答我的问题"}];
    let form = layui.form;
    let uid = genUID()

    function genUID() {
        let buf = new Uint32Array(1);
        window.crypto.getRandomValues(buf);
        return buf[0].toString(16);
    }

    function toBase64(buffer) {
        let binary = "";
        let bytes = new Uint8Array(buffer);
        let len = bytes.byteLength;
        for (let i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    }

    function countdown() {
        let seconds = 60;
        btnControl.innerHTML = `<i class="layui-icon layui-icon-radio" style="font-size: 20px; color: #ba1616;"></i>录音中（${seconds}s）`;
        countdownInterval = setInterval(() => {
            seconds = seconds - 1;
            if (seconds <= 0) {
                clearInterval(countdownInterval);
                recorder.stop();
            } else {
                btnControl.innerHTML = `<i class="layui-icon layui-icon-radio" style="font-size: 20px; color: #ba1616;"></i>录音中（${seconds}s）`;
            }
        }, 1000);
    }

    function changeBtnStatus(status) {
        btnStatus = status;
        if (status === "CONNECTING") {
            btnControl.innerText = "建立连接中";
            document.getElementById("result").innerText = "";
            resultText = "";
            resultTextTemp = "";
        } else if (status === "OPEN") {
            countdown();
        } else if (status === "CLOSING") {
            btnControl.innerText = "关闭连接中";
        } else if (status === "CLOSED") {
            btnControl.innerHTML = "<i class=\"layui-icon layui-icon-left\" style=\"font-size: 20px; color: #16baaa;\"></i>开始听写";
        }
    }

    function renderResult(resultData) {
        // 识别结束
        let jsonData = JSON.parse(resultData);
        if (jsonData.data && jsonData.data.result) {
            let data = jsonData.data.result;
            let str = "";
            let ws = data.ws;
            for (let i = 0; i < ws.length; i++) {
                str = str + ws[i].cw[0].w;
            }
            // 开启wpgs会有此字段(前提：在控制台开通动态修正功能)
            // 取值为 "apd"时表示该片结果是追加到前面的最终结果；取值为"rpl" 时表示替换前面的部分结果，替换范围为rg字段
            if (data.pgs) {
                if (data.pgs === "apd") {
                    // 将resultTextTemp同步给resultText
                    resultText = resultTextTemp;
                }
                // 将结果存储在resultTextTemp中
                resultTextTemp = resultText + str;
            } else {
                resultText = resultText + str;
            }
            document.getElementById("result").innerText = resultTextTemp || resultText || "";
        }
        if (jsonData.code === 0 && jsonData.data.status === 2) {
            iatWS.close();
        }
        if (jsonData.code !== 0) {
            iatWS.close();
            console.error(jsonData);
        }
    }

    function iatConnectWebSocket() {
        let data = form.val('iat-filter');
        const websocketUrl = getWebSocketUrl("wss://iat-api.xfyun.cn/v2/iat", "/v2/iat", data.iat_app_key, data.iat_app_secret);
        if ("WebSocket" in window) {
            iatWS = new WebSocket(websocketUrl);
        } else if ("MozWebSocket" in window) {
            iatWS = new MozWebSocket(websocketUrl);
        } else {
            alert("浏览器不支持WebSocket");
            return;
        }
        changeBtnStatus("CONNECTING");
        iatWS.onopen = (e) => {
            // 开始录音
            recorder.start({
                sampleRate: 16000, frameSize: 1280,
            });
            let params = {
                common: {
                    app_id: data.iat_appid,
                }, business: {
                    language: "zh_cn", domain: "iat", accent: "mandarin", vad_eos: 5000, dwa: "wpgs",
                }, data: {
                    status: 0, format: "audio/L16;rate=16000", encoding: "raw",
                },
            };
            iatWS.send(JSON.stringify(params));
        };
        iatWS.onmessage = (e) => {
            renderResult(e.data);
        };
        iatWS.onerror = (e) => {
            console.error(e);
            recorder.stop();
            changeBtnStatus("CLOSED");
        };
        iatWS.onclose = (e) => {
            recorder.stop();
            changeBtnStatus("CLOSED");
        };
    }

    recorder.onFrameRecorded = ({isLastFrame, frameBuffer}) => {
        if (iatWS.readyState === iatWS.OPEN) {
            iatWS.send(JSON.stringify({
                data: {
                    status: isLastFrame ? 2 : 1,
                    format: "audio/L16;rate=16000",
                    encoding: "raw",
                    audio: toBase64(frameBuffer),
                },
            }));
            if (isLastFrame) {
                changeBtnStatus("CLOSING");
            }
        }
    };
    recorder.onStop = () => {
        clearInterval(countdownInterval);
    };

    function recordButton() {
        if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {
            iatConnectWebSocket();
        } else if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {
            // 结束录音
            recorder.stop();
        }
    }

    btnControl.onclick = recordButton;

    let bucket = []

    function chatConnectWebSocket() {
        let data = form.val('chat-filter');
        const websocketUrl = getWebSocketUrl("wss://spark-api.xf-yun.com/v3.5/chat", "/v3.5/chat", data.chat_app_key, data.chat_app_secret);
        if ("WebSocket" in window) {
            chatWS = new WebSocket(websocketUrl);
        } else if ("MozWebSocket" in window) {
            chatWS = new MozWebSocket(websocketUrl);
        } else {
            alert("浏览器不支持WebSocket");
            return;
        }
        chatWS.onopen = (e) => {
            if (text.length > 100) {
                text.splice(0, text.length - 100)
            }
            let content = document.getElementById("result").value;
            text.push({"role": "user", "content": content})
            let params = {
                "header": {
                    "app_id": data.chat_appid, "uid": uid
                }, "parameter": {
                    "chat": {
                        "domain": "generalv3", "temperature": 0.5, "max_tokens": 8192,
                    }
                }, "payload": {
                    "message": {
                        "text": text
                    }
                }
            };
            chatWS.send(JSON.stringify(params));
            chatBoxControl.innerHTML += "<div class=\"message_common message_me\">" + content + "</div>"
            document.getElementById("result").innerText = ""
        }
        chatWS.onmessage = (e) => {
            console.log(e.data);
            let jo = JSON.parse(e.data).payload.choices
            bucket.push(jo.text[0])
            if (jo.status === 0) {
                chatBoxControl.innerHTML += "<div class=\"message_common message_chat\">" + jo.text[0].content + "</div>"
                box.scrollTop = box.scrollHeight
            }
            if (jo.status === 1) {
                let messages = chatBoxControl.children
                messages[messages.length - 1].innerText += jo.text[0].content
                box.scrollTop = box.scrollHeight
            }
            if (jo.status === 2) {
                let messages = chatBoxControl.children
                messages[messages.length - 1].innerText += jo.text[0].content
                box.scrollTop = box.scrollHeight
                let content = bucket.map(b => {
                    return b.content
                }).join();
                text.push({"role": "assistant", content: content})
                bucket = []
            }
        };
        chatWS.onerror = (e) => {
            console.error(e);
        };
    }

    function sendButton() {
        chatConnectWebSocket()
    }

    sendControl.onclick = sendButton

    window.addEventListener("keydown", function (event) {
        if (event.code === "ArrowLeft") {
            recordButton();
        } else if (event.code === "ArrowRight") {
            if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {
                // 结束录音
                recorder.stop();
            }
            sendButton();
        } else if (event.code === "ArrowUp") {
            document.getElementById("result").innerText = ""
        }
    })
})();
